package com.miplus.ccrm.core.service.action;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.miplus.ccrm.common.CmdResVo;
import com.miplus.ccrm.common.EnumRCode;
import com.miplus.ccrm.common.JPubUtils;
import com.miplus.ccrm.common.ServiceException;
import com.miplus.ccrm.core.controller.vo.action.*;
import com.miplus.ccrm.core.controller.vo.conf.WfNextStepVo;
import com.miplus.ccrm.core.pojo.FiDelay;
import com.miplus.ccrm.core.mapper.FiDelayMapper;
import com.miplus.ccrm.core.service.FiWorkFlowCase;
import com.miplus.ccrm.core.service.conf.MsgAlertsService;
import com.miplus.ccrm.core.service.collect.FiTaskService;
import com.miplus.ccrm.core.service.strategy.CpCalllistService;
import com.miplus.ccrm.core.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
* @author pc
* @description 针对表【fi_delay(留案申请表)】的数据库操作Service实现
* @createDate 2024-04-08 10:12:10
*/
@Slf4j
@Service
public class FiDelayServiceImpl extends MPJBaseServiceImpl<FiDelayMapper, FiDelay>
    implements FiDelayService{
    @Resource
    private FiTaskService fiTaskService;
    @Resource
    private CpCalllistService cpCalllistService;
    @Resource
    private FiWorkFlowCase fiWorkFlowCase;
    @Resource
    private MsgAlertsService msgAlertsService;

    @Override
    public IPage<FiDelayResVo> fiDelayList(String $usrid, FiApplyReqVo paras)
    {
        return selectJoinListPage(new Page<>(paras.getPageNum(), paras.getPageSize()),
                FiDelayResVo.class,
                new MPJLambdaWrapper<FiDelay>()
                        .selectAs("fun_getnames('FI.DELAY.STATUS',t.status)", FiDelayResVo::getStatusdsc)
                        .selectAs("fun_getnames('FI.DELAY.REASON',t.applyreason)", FiDelayResVo::getApplyreasondsc)
                        .selectAs("(select cl.wfid from cp_calllist cl where cl.clid=t.clid)", FiDelayResVo::getWfid)
                        .selectAs("fun_getgrpname(t.applyusr)",FiDelayResVo::getApplygrpname)
                        .selectAll(FiDelay.class)
                        .apply("fc_hasApplyView(t.applynumber,'SYS_DELAY',t.applyusr,{0},t.status,t.confirmusr)>0",$usrid)
                        .apply(JPubUtils.IsNotEmpty(paras.getApplygrp()),"fc_hasUsrInGroup(t.applyusr,{0})>0",paras.getApplygrp())
                        .eq(JPubUtils.IsNotEmpty(paras.getFicaseid()), FiDelay::getFicaseid,paras.getFicaseid())
                        .eq(JPubUtils.IsNotEmpty(paras.getStatus()),FiDelay::getStatus,paras.getStatus())
                        .eq(JPubUtils.IsNotEmpty(paras.getApplyusr()),FiDelay::getApplyusr,paras.getApplyusr())
                        .between(JPubUtils.IsNotEmpty(paras.getStartdt()), FiDelay::getApplydt,JPubUtils.StringToDate(paras.getStartdt()),JPubUtils.StringToDate(paras.getEnddt()))
                        .orderByAsc(FiDelay::getApplydt)
        );
    }

    @Override
    @Transactional
    public CmdResVo fiDelayAdd(String $usrid, FiDelayAddVo paras)
    {
        //1=待审核
        List<FiDelay> fiDelay=selectJoinList(FiDelay.class,
                new MPJLambdaWrapper<FiDelay>()
                        .eq(FiDelay::getFicaseid,paras.getFicaseid())
                        .in(FiDelay::getStatus,
                                EnumConfirmStatus.New.value,EnumConfirmStatus.Pending.value,
                                EnumConfirmStatus.Process.value,EnumConfirmStatus.Pass.value)
        );
        //相同的案件正在审核中
        if(JPubUtils.IsNotEmpty(fiDelay)){
            throw new ServiceException(EnumRCode.DataProcess.value, EnumRCode.DataProcess.name);
        }
        String clid=paras.getClid();
        if(JPubUtils.IsEmpty(clid)){
            clid="SYS_DELAY"; //此任务是系统配置任务，不能delete
        }

        Integer wfid=cpCalllistService.getCalllistWfID(clid);

        //CAMPAIGN.CHANNEL=11留案
        int tasknumber=fiTaskService.addTask($usrid,clid,paras.getFicaseid(), EnumFiChannel.Delay.value);

        int ret=0;
        log.info("applyAdd:clid={},ficase={},tasknumber={},wfid={}",clid,paras.getFicaseid(),tasknumber,wfid);

        FiDelay fi = new FiDelay();
        fi.setClid(clid);
        if(paras.getDelaydays()!=null) {
            fi.setDelaydays(paras.getDelaydays());
        }
        fi.setApplyreason(paras.getApplyreason());
        fi.setFicaseid(paras.getFicaseid());
        fi.setApplydsc(paras.getApplydsc());
        fi.setTasknumber(tasknumber);
        fi.setStatus(EnumConfirmStatus.New.value); //新建
        fi.setApplydt(new Date());
        fi.setApplyusr($usrid);
        ret=baseMapper.insert(fi);

        int applynumber=fi.getApplynumber();

        if(wfid>0){
            //wfid=0 表示此任务clid没有配置工作流，前台可以根据是否有wfid显示不通的审批流程或状态
            String status=fiWorkFlowCase.doCreate($usrid,wfid,applynumber,tasknumber);
            fi = new FiDelay();
            fi.setApplynumber(applynumber);
            fi.setStatus(Integer.parseInt(status)); //处理中
            baseMapper.updateById(fi);
        }

        return new CmdResVo(ret,Integer.toString(applynumber));
    }

    @Override
    public CmdResVo fiDelayCancel(String $usrid, FiApplyCancelVo paras)
    {
        FiDelay fi=baseMapper.selectById(paras.getApplynumber());
        if(JPubUtils.IsNotEmpty(fi.getTasknumber())){
            fiTaskService.updateStatus(fi.getTasknumber(),$usrid,"X");
        }
        else{
            log.warn("applyCancel:getTasknumber.isnull");
        }
        Integer wfid=cpCalllistService.getCalllistWfID(fi.getClid());
        fiWorkFlowCase.doCancel($usrid,wfid,fi.getApplynumber());

        fi = new FiDelay();
        fi.setApplynumber(paras.getApplynumber());
        fi.setStatus(EnumConfirmStatus.Cancel.value); //取消
        fi.setCancelusr($usrid);
        fi.setCanceldt(new Date());
        int ret=baseMapper.updateById(fi);

        return new CmdResVo(ret,fi.getApplynumber().toString());
    }

    @Override
    public void doCancel(String $usrid, List<Integer> ficaseids,int enstatus)
    {//留案申请过程中，如果回收，分案，出催后，自动取消申请
        MPJLambdaWrapper<FiDelay> quyWrapper=new MPJLambdaWrapper<FiDelay>()
                .eq(FiDelay::getStatus, enstatus);

        if(ficaseids.size()<=1000) {
            quyWrapper.in(FiDelay::getFicaseid, ficaseids);
        }
        else{
            List<List<Integer>> newList= ListUtils.partition(ficaseids,1000);
            quyWrapper.and(p->{
                for(List<Integer> list : newList){
                    p.or().in(FiDelay::getFicaseid,list);
                }
            });
        }
        List<FiDelay> filist = baseMapper.selectList(quyWrapper);

        if(JPubUtils.IsEmpty(filist)) return;

        for (FiDelay fi : filist){
            log.info("doCancel({}):Status={} By {}",fi.getFicaseid(),enstatus,$usrid);
            if(enstatus==EnumConfirmStatus.Pending.value) {
                if (JPubUtils.IsNotEmpty(fi.getTasknumber())) {
                    fiTaskService.updateStatus(fi.getTasknumber(), $usrid, "X");
                }
                Integer wfid = cpCalllistService.getCalllistWfID(fi.getClid());
                fiWorkFlowCase.doCancel($usrid, wfid, fi.getApplynumber());
            }
            fi.setStatus(EnumConfirmStatus.Cancel.value); //取消
            fi.setCancelusr($usrid);
            fi.setCanceldt(new Date());
            baseMapper.updateById(fi);
        }
    }

    @Override
    public CmdResVo fiDelayConfirm(String $usrid, FiApplyConfirmVo paras)
    {
        boolean confirmend=true;
        String okstatus=paras.getActionid().toString();
        FiDelay fiDelay=baseMapper.selectById(paras.getApplynumber());
        if(JPubUtils.IsNotEmpty(paras.getCaseactid())){
            //需要走工作流
            WfNextStepVo wfNextStepVo=fiWorkFlowCase.doExec($usrid,paras.getCaseactid(),
                    paras.getActionid(),paras.getWfcaseid(),paras.getConfirmdsc()
            );
            okstatus=wfNextStepVo.getStatus();

            //可能有多级审核,3=审核全部完成
            if(!JPubUtils.IsEqual(wfNextStepVo.getType(), EnumWorkFlowStep.End.value)) {
                confirmend=false;
            }
        }
        else{
            Integer wfid=cpCalllistService.getCalllistWfID(fiDelay.getClid());
            if(wfid==null||wfid==0){//不使用工作流,这种情况下okstatus就是字典ID，直接写审核结果
                log.info("fiDeductConfirm.nouse workflow：okstatus={}",okstatus);
            }
            else{//可能配置错误或网络引起的，2024-08-29
                log.warn("fiDeductConfirm.nofind wf caseactid.");
                throw new ServiceException(EnumRCode.WfDataErr.value, EnumRCode.WfDataErr.name);
            }
        }

        //单纯就是审批流程，结果后续操作就在这里写，如果有后续反馈的，在result里面写，比如外访
        if(JPubUtils.IsNotEmpty(fiDelay.getTasknumber())&&confirmend) {
            /*HZbank的留案比较特殊，留案操作不直接增加绑定日期，只做标识，下次分案是分给上次申请留案的组
            if(JPubUtils.IsEqual(okstatus,"2")){//审核通过
                FiCreditcases fcase=fiCreditcasesService.getById(fiDelay.getFicaseid());
                log.info("applyConfirm.Ok:ficaseid={} Bindenddt.adddays={}",
                        fiDelay.getFicaseid(),fiDelay.getDelaydays()
                );
                Date addday=JPubUtils.addDays(fcase.getBindenddt(),fiDelay.getDelaydays());
                fcase.setBindenddt(addday);
                fiCreditcasesService.getBaseMapper().updateById(fcase);
                fiTaskService.updateStatus(fiDelay.getTasknumber(), $usrid, "R");
            }
            else{//审核不通过
                fiTaskService.updateStatus(fiDelay.getTasknumber(), $usrid, "F");
            }*/
            fiTaskService.updateStatus(
                    fiDelay.getTasknumber(),
                    $usrid,
                    fiWorkFlowCase.getPassStatus(okstatus)
            );
            msgAlertsService.msgAlertAdd(EnumFiChannel.Delay,
                    fiDelay.getApplyusr(),
                    $usrid, EnumUtil.ConfirmStatusName(okstatus)
            );
        }

        FiDelay fi = new FiDelay();
        fi.setApplynumber(paras.getApplynumber());
        fi.setStatus(Integer.parseInt(okstatus));
        fi.setConfirmusr($usrid);
        fi.setConfirmdt(new Date());
        fi.setConfirmdsc(paras.getConfirmdsc());
        int ret=baseMapper.updateById(fi);

        return new CmdResVo(ret,paras.getApplynumber().toString());
    }

    @Override
    @Transactional
    public CmdResVo fiDelayListAdd(String $usrid, DelayListAddVo paras)
    {
        String clid=paras.getClid();
        if(JPubUtils.IsEmpty(clid)){
            clid="SYS_DELAY";
        }
        Integer wfid=cpCalllistService.getCalllistWfID(clid);
        int ret = 0;
        for(Integer ficaseid : paras.getFicaseList()) {
            FiDelay fiDelay=selectJoinOne(FiDelay.class,
                    new MPJLambdaWrapper<FiDelay>()
                            .eq(FiDelay::getFicaseid,ficaseid)
                            .in(FiDelay::getStatus,
                                    EnumConfirmStatus.New.value,EnumConfirmStatus.Pending.value,
                                    EnumConfirmStatus.Process.value,EnumConfirmStatus.Pass.value)
            );

            if(fiDelay!=null){
                log.info("fiDelayListAdd:ficase={} existdelay", ficaseid);
                continue;
            }
            int tasknumber = fiTaskService.addTask($usrid, clid, ficaseid, EnumFiChannel.Delay.value);

            log.info("fiDelayListAdd:clid={},ficase={},tasknumber={},wfid={}", clid, ficaseid, tasknumber, wfid);

            FiDelay fi = new FiDelay();
            fi.setClid(clid);
            if (paras.getDelaydays() != null) {
                fi.setDelaydays(paras.getDelaydays());
            }
            fi.setApplyreason(paras.getReason());
            fi.setFicaseid(ficaseid);
            fi.setApplydsc(paras.getApplydsc());
            fi.setTasknumber(tasknumber);
            fi.setStatus(EnumConfirmStatus.New.value); //新建
            fi.setApplydt(new Date());
            fi.setApplyusr($usrid);
            ret = baseMapper.insert(fi);

            int applynumber = fi.getApplynumber();

            if (wfid > 0) {
                //wfid=0 表示此任务clid没有配置工作流，前台可以根据是否有wfid显示不通的审批流程或状态
                String status = fiWorkFlowCase.doCreate($usrid, wfid, applynumber, tasknumber);
                fi = new FiDelay();
                fi.setApplynumber(applynumber);
                fi.setStatus(Integer.parseInt(status)); //处理中
                baseMapper.updateById(fi);
            }
            ret++;
        }

        return new CmdResVo(ret);
    }
}




